#ifndef _csBuffer_h_
#define _csBuffer_h_

/********************************************************************
	created:	2009/11/28
	created:	28:11:2009   12:45
	filename: 	e:\CrazySprite\code\src\cscorelib\csBuffer.h
	file path:	e:\CrazySprite\code\src\cscorelib
	file base:	csBuffer
	file ext:	h
	author:		dongchengok
	
	purpose:	buffer
*********************************************************************/
#include "csType.h"

#define csDEFINE_BUFFER(classname, chartype, strdupfunc)                      \
class classname                                            \
{                                                                           \
public:                                                                     \
	classname(const chartype *str = NULL)                                   \
	: m_str(str ? strdupfunc(str) : NULL)                               \
	{                                                                       \
	}                                                                       \
	\
	classname(size_t len)                                                   \
	: m_str((chartype *)malloc((len + 1)*sizeof(chartype)))             \
	{                                                                       \
	m_str[len] = (chartype)0;                                           \
	}                                                                       \
	\
	/* no need to check for NULL, free() does it */                         \
	~classname() { free(m_str); }                                           \
	\
	/*                                                                      \
WARNING:                                                            \
\
the copy ctor and assignment operators change the passed in object  \
even although it is declared as "const", so:                        \
\
a) it shouldn't be really const                                     \
b) you shouldn't use it afterwards (or know that it was reset)      \
\
This is very ugly but is unfortunately needed to make the normal use\
of classname buffer objects possible and is very similar to what    \
std::auto_ptr<> does (as if it were an excuse...)                   \
*/                                                                      \
	\
	/*                                                                      \
because of the remark above, release() is declared const even if it  \
isn't really const                                                   \
*/                                                                     \
	chartype *release() const                                               \
	{                                                                       \
	chartype *p = m_str;                                                \
	((classname *)this)->m_str = csNULL;                                  \
	return p;                                                           \
	}                                                                       \
	\
	void reset()                                                            \
	{                                                                       \
	free(m_str);                                                        \
	m_str = NULL;                                                       \
	}                                                                       \
	\
	classname(const classname& src)                                         \
	: m_str(src.release())                                              \
	{                                                                       \
	}                                                                       \
	\
	classname& operator=(const chartype *str)                               \
	{                                                                       \
	free(m_str);                                                        \
	m_str = str ? strdupfunc(str) : csNULL;                               \
	return *this;                                                       \
	}                                                                       \
	\
	classname& operator=(const classname& src)                              \
	{                                                                       \
	free(m_str);                                                        \
	m_str = src.release();                                              \
	\
	return *this;                                                       \
	}                                                                       \
	\
	bool extend(size_t len)                                                 \
	{                                                                       \
	chartype *                                                          \
	str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype));   \
	if ( !str )                                                         \
	return false;                                                   \
	\
	m_str = str;                                                        \
	\
	return true;                                                        \
	}                                                                       \
	\
	chartype *data() { return m_str; }                                      \
	const chartype *data() const { return m_str; }                          \
	operator const chartype *() const { return m_str; }                     \
	chartype operator[](size_t n) const { return m_str[n]; }                \
	\
private:                                                                    \
	chartype *m_str;                                                        \
}


#define csDEFINE_WRITABLE_BUFFER(classname, baseclass, chartype)              \
class classname : public baseclass                         \
{                                                                           \
public:                                                                     \
	classname(const baseclass& src) : baseclass(src) {}                     \
	classname(const chartype *str = csNULL) : baseclass(str) {}               \
	\
	operator chartype*() { return this->data(); }                           \
}

csDEFINE_BUFFER(csCharBuffer, c8, _strdup);
csDEFINE_WRITABLE_BUFFER(csWritableCharBuffer, csCharBuffer, c8);

csDEFINE_BUFFER(csWCharBuffer, c16, _wcsdup);
csDEFINE_WRITABLE_BUFFER(csWritableWCharBuffer, csWCharBuffer, c16);


#endif // _csBuffer_h_